﻿using AiQiuQuan.Sport.Core;
using AiQiuQuan.Sport.Core.WechatApi;
using AiQiuQuan.Sport.Model.Models;
using SKIT.FlurlHttpClient.Wechat.Api;
using SKIT.FlurlHttpClient.Wechat.Api.Models;
using SKIT.FlurlHttpClient.Wechat.Api.Utilities;

namespace AiQiuQuan.Sport.WebApi.Services
{
    /// <summary>
    /// 第三方获取用户信息
    /// </summary>
    public class ThirdUserInfoService : IThirdUserInfoService
    {
        private readonly WechatApiOption _wechatApiOption;
        private readonly ILogger<ThirdUserInfoService> _logger;
        private readonly IWechatApiHttpClientFactory _wechatApiHttpClientFactory;
        private readonly IAccessTokenService _accessTokenService;

        /// <summary>
        /// ctor
        /// </summary>
        public ThirdUserInfoService(
            WechatApiOption wechatApiOption,
            ILogger<ThirdUserInfoService> logger,
            IWechatApiHttpClientFactory wechatApiHttpClientFactory,
            IAccessTokenService accessTokenService)
        {
            _wechatApiOption = wechatApiOption;
            _logger = logger;
            _wechatApiHttpClientFactory = wechatApiHttpClientFactory;
            _accessTokenService = accessTokenService;
        }

        /// <summary>
        /// 微信公众号获取用户信息
        /// </summary>
        /// <param name="webAccessToken">网页授权accessToken</param>
        /// <param name="openId">用户openid</param>
        /// <returns></returns>
        public async Task<UnaryResult<WxUserInfoDto>> GetWxMpUserInfoAync(string webAccessToken, string openId)
        {
            var userinfo = new WxUserInfoDto();
            var apiClient = _wechatApiHttpClientFactory.Create(_wechatApiOption.MPAppId, _wechatApiOption.MPAppSecret);
            var request = new SnsUserInfoRequest { AccessToken = webAccessToken, OpenId = openId };
            var rep = await apiClient.ExecuteSnsUserInfoAsync(request);
            if (!rep.IsSuccessful())
            {
                var error = $"微信获取用户信息异常:{rep.ErrorCode},{rep.ErrorMessage}";
                _logger.LogError(error);
                return UnaryResult.From(10, userinfo, error);
            }

            userinfo.MpOpenId = rep.OpenId;
            userinfo.UnionId = rep.UnionId;
            userinfo.NickName = rep.Nickname;
            userinfo.HeadImgUrl = rep.HeadImageUrl;
            userinfo.Privilege = rep.PrivilegeList;

            return UnaryResult.Succeed(userinfo);
        }

        /// <summary>
        /// 获取微信小程序用户电话
        /// </summary>
        /// <param name="code">小程充获取的动态口令</param>
        public async Task<UnaryResult<WxMiniProgramPhoneDto>> GetWxMiniprogramPhoneAsync(string code)
        {
            var tokenResult = await _accessTokenService.GetWxMiniProgramAccessTokenAsync();
            if (tokenResult.Code != 0)
            {
                return UnaryResult.From<WxMiniProgramPhoneDto>(tokenResult.Code, null, tokenResult.Msg);
            }

            var request = new WxaBusinessGetUserPhoneNumberRequest
            {
                AccessToken = tokenResult.Data.AccessToken,
                Code = code
            };
            var client = _wechatApiHttpClientFactory.Create(_wechatApiOption.MiniProgramAppId, _wechatApiOption.MiniProgramAppSecret);
            var rep = await client.ExecuteWxaBusinessGetUserPhoneNumberAsync(request);
            if (!rep.IsSuccessful())
            {
                return UnaryResult.From<WxMiniProgramPhoneDto>(10, null, $"{rep.ErrorCode},{rep.ErrorMessage}");
            }

            var result = new WxMiniProgramPhoneDto
            {
                PhoneNumber = rep.PhoneInfo.PhoneNumber,
                PurePhoneNumber = rep.PhoneInfo.PurePhoneNumber,
                countryCode = rep.PhoneInfo.CountryCode,
                Watermark = rep.PhoneInfo.Watermark
            };
            return UnaryResult.Succeed(result);
        }

        /// <summary>
        /// 解密微信小程序前端获取的相关开放数据
        /// </summary>
        /// <typeparam name="TData">数据类型</typeparam>
        /// <param name="sessionKey">base64 sessionKey</param>
        /// <param name="iv">base64 iv</param>
        /// <param name="encryptData">base64 encryptDtata</param>
        /// <returns></returns>
        public UnaryResult<TData> DecryptWxMiniprogramData<TData>(string sessionKey, string iv, string encryptData)
        {
            try
            {
                var plainData = AESUtility.DecryptWithCBC(sessionKey, iv, encryptData);
                var data = System.Text.Json.JsonSerializer.Deserialize<TData>(plainData);
                return UnaryResult.Succeed<TData>(data);
            }
            catch (Exception ex)
            {
                return UnaryResult.From<TData>(10, default, ex.Message);
            }
        }
    }
}